" Description: Neovim basic configurations

" { Utility funcs
    function! OSX()
        return has('macunix')
    endfunction
    function! LINUX()
        return has('unix') && !has('macunix') && !has('win32unix')
    endfunction
    function! WIN()
        return has('win16') || has('win32') || has('win64')
    endfunction
    function! GUI()
        return has('gui_running')
    endfunction

" }
" { 界面
    " 显示行号
    set number
    " 隐藏所有GUI组件
    "       m:菜单栏
    "       T:工具栏
    "       l:左侧滚动条
    "       L:分割窗口时左侧滚动条
    "       r:右侧滚动条
    "       b:底部滚动条
    set guioptions=
    " 设置显示不可见字符
    set list
    " 设置不可见字符样式
    set listchars=tab:>\ ,precedes:<,extends:>,eol:~       " trail:.
    " 自动调整窗口高度. 影响coc.nvim插件函数提示窗口大小
    set winheight=9
    autocmd BufEnter * call s:set_colorcolumn()
    function s:set_colorcolumn()
        let t = &filetype
        if (t == 'rust')
            set winwidth=108
            set colorcolumn=100
        elseif (t == 'exproject')
            " exproject插件进入时, 不自动调整窗口
        else
            " 自动调整窗口宽度
            set winwidth=88
            " 显示右边界线
            set colorcolumn=80
        endif
    endfunction
    " 强制窗口最小宽度
    set winminwidth=1
    " 强制窗口最小高度
    set winminheight=1
    " 窗口启动时自动最大化
    " au GUIEnter * simalt ~x
    " vi兼容行为
    set cpoptions=aABcdeFs
    au VimEnter * set cpoptions=aABcdeFs
    " 设置窗口大小
    if has('autocmd')
        autocmd GUIEnter * winsize 120 36
    endif
    " 分割或关闭窗口时自动进行等分(关闭)
    set noequalalways
    " 水平分割光标在下面窗口
    set splitbelow
    " 垂直分割光标在右边窗口
    set splitright
" }
" { 字体
    " 使用英文菜单
    set langmenu=none
    " 所有文字提示都使用英文
    if WIN()
        silent exec 'language english'
    elseif OSX()
        silent exec 'language en_US'
    else
        let s:uname = system('uname -s')
        if s:uname == 'Darwin\n'
            " in mac-terminal
            silent exec 'language en_US'
        else
            " in linux-terminal
            silent exec 'language en_US.utf8'
        endif
    endif
    " 设置默认字体
    if GUI()
        augroup ex_gui_font
            " check and determine the gui font after GUIEnter.
            " NOTE: getfontname function only works after GUIEnter.
            au!
            au GUIEnter * call s:set_gui_font()
        augroup END
        " set guifont
        function! s:set_gui_font()
            if has('gui_gtk2')
                if getfontname( 'DejaVu Sans Mono' ) != ''
                    set guifont=DejaVu\ Sans\ Mono\ 9
                else
                    set guifont=Monospace\ 8
                endif
            elseif has('x11')
                " Also for GTK 1
                set guifont=*-lucidatypewriter-medium-r-normal-*-*-180-*-*-m-*-*
            elseif OSX()
                if getfontname( 'DejaVu Sans Mono' ) != ''
                    set guifont=DejaVu\ Sans\ Mono:h8
                endif
            elseif WIN()
                if getfontname( 'Consolas' ) != ''
                    set guifont=Consolas:h8:cANSI " this is the default visual studio font
                    set guifontwide=Consolas:h8:cANSI
                    " 中文设置为微软雅黑，需要安装YaHei Consolas Hybrid字体
                    " set guifontwide=YaHei\ Consolas\ Hybrid:h8:cANSI
                elseif getfontname( 'DejaVu Sans Mono' ) != ''
                    set guifont=DejaVu\ Sans\ Mono:h8:cANSI
                else
                    set guifont=Lucida_Console:h8:cANSI
                endif
            endif
        endfunction
    endif
" }
" { ctags
    " 打开文件时自动切换到文件所在的目录
    " set autochdir
    " set tags=tags
    " set tags+=./.exvim.*/tags,./**/tags
    " autocmd VimEnter * set tags+=./tags
" }
" { cscope
    if has('cscope')
        " ### Cscope插件配置
        "       设定是否使用quickfix窗口来显示cscope结果
        set cscopequickfix=s-,c-,d-,i-,t-,e-
    endif
" }
" { 状态栏
    " 总是显示状态栏
    set laststatus=2
"     " 显示光标位置(不使用，直接设置显示格式)
"     set ruler
    " 显示状态栏信息，显示格式设置
    let slFuncPrototype ='' " '%{EchoFuncGetStatusLine()}'
    let slWinType       ='%q'
    let slFileName      ='%f'
    let slFileStatus    ='%2*%h%r%m%*%w'
    let slArgStatus     ='%a'
    let slGitStatus     ='' " '%{fugitive#statusline()}'
    let slFileType      ='%y'
    let slFileEncoding  =' %{(&fenc == ""?&enc:&fenc).(&bomb?",BOM":"")}'
    let slFileFormat    =' %{&ff}'
    let slFilePosition  =' %4*%l/%L,%v-0x%02B%*'
    let slString        =slFuncPrototype
                \.'%<'.slWinType.slFileName.slFileStatus.' '
                \.'%='.slArgStatus.slGitStatus.slFileType
                \.slFileEncoding.slFilePosition
    set statusline      =%!slString
    " 设置状态栏高亮配色(在配色方案文件中设置)
" }
" { 命令行
    " 命令行补全
    set wildmenu
    " 显示已输入的组合命令部分
    set showcmd
    " Linux下设置失效，需要在VimEnter时重新设置
    autocmd VimEnter * set showcmd
    " 1 screen lines to use for the command-line
    set cmdheight=1
" }
" { 编码
    " 启用文件类型侦测
    filetype on
    " 针对不同的文件类型加载对应的插件
    filetype plugin on
    " 启用缩进
    filetype plugin indent on
    " 设置gvim内部编码
    set encoding=utf-8
    " 设置当前编辑文件编码
    set fileencoding=utf-8
    " 设置支持打开的文件的编码
    set fileencodings=ucs-bom,utf-8,gbk,cp936,gb2312,gb18030,bug5,eucjp,euc-kr,latin-1,chinese
    " 设置新文件的<EOL>格式
    set fileformat=unix
    " 给出文件的<EOL>格式类型，默认 ffs=dos,unix
    set fileformats=unix,dos,mac
    " 重置菜单显示，解决菜单乱码
    " source $VIMRUNTIME/delmenu.vim
    " source $VIMRUNTIME/menu.vim
    " 设置终端输出编码(解决控制台乱码)
    language messages en_US.UTF-8               " zh_CN.UTF-8
    " 设置终端编码为gvim内部编码encoding
    let &termencoding=&encoding
    " set termencoding=gbk,utf8,cp936,gb18030,gb2312,ucs-bom,latin-1  "gb18030,cp936,utf-8

    " Windows终端下特别配置, Windows console 下只能是gbk
    if !GUI() && WIN()
        set encoding=gbk
        set fileencoding=gbk
        language messages en_US.gbk           " zh_CN.gbk
        let &termencoding=&encoding
    end
" }
" { 编辑
    " 光标移动换行  b:退格键  s:空格键  <,>:方向键  [,]:插入模式下方向键
    set whichwrap=b,s,<,>,[,]
    " 光标接近上下端时自动滚动
    set scrolloff=4
    " 光标接近左右端时自动滚动
    set sidescroll=8
    " 不设定在插入状态无法用退格键和 Delete 键删除换行符
    set backspace=indent,eol,start
    " 扩展制表符，将输入的Tab替换为空格
    set expandtab
    " 制表符长度(通用的文档制表符长度设置为8)
    set tabstop=4
    " 智能对齐
    set nosmartindent
    " 自动缩进
    set autoindent
    " 指定按一次backspace就删除shiftwidth宽度的空格
    set smarttab
    " 设置C语言Tab长度为4个空格
    set cindent shiftwidth=4
    " 设置C语言缩进规则(参考help手册)
    set cinoptions=l1,g0
    " 设置<c-a>递增<c-x>递减时，支持的字符格式
    "       alpha: 字母
    "       hex: '0x'开头的16进制数值
    "       octal: '0'开头的8进制数值
    set nrformats=hex,octal
    autocmd BufEnter * call s:set_indent()
    function s:set_indent()
        let t = &filetype
        if (t == 'go' || t == 'sql' || t == 'json' || t == 'yaml' || t == 'vue'
                    \ || t == 'html' || t == 'javascript' || t == 'css'
                    \ || t == 'less' || t == 'scss' || t == 'sass'
                    \ || t == 'python' || t == 'vim' || t == 'lua' || t == 'zsh')
            set tabstop=2
            set shiftwidth=2
        else
            set tabstop=4
            set shiftwidth=4
        endif
        " 强制使用tab缩进
        if (t == 'python')
            setlocal noexpandtab
        endif
    endfunction
" }
" { 搜索
    " 使用'/'搜索的输入过程中即时搜索，自动跳转到光标后的第一个匹配项
    set incsearch
    " 搜索忽略大小写
    set ignorecase
    " 有一个或以上大写字母时仍保持对大小写敏感
    set smartcase
" }
" { 补全
    " 设置自动补全提示内容的获取范围
    " i:    搜索包含，include文件较多时速度极慢；使用<c-x><c-i>搜索include
    " t:    搜索tags，tags文件较大时速度较慢；使用<c-x><c-]>搜索tags
    set complete=.,w,b,u,U,k,s
    " 设置补全选项
    "       menuone:  总是弹出补全项菜单
    "       longest:  使用最常用的候选项
    "       preview:  弹出补全项的详细信息窗口
    set completeopt=menuone,longest
    " 设置补全信息预览窗口高度
    set previewheight=9
    " 锁定补全信息预览窗口高度
    set winfixheight
" }
" { 高亮
    " 显示语法高亮
    syntax enable
    syntax on
    set termguicolors
    " 高亮显示匹配括号
    set matchpairs=(:),[:],{:}
    " 输入符号时，光标跳转到匹配的括号
    set showmatch
    " 输入符号时，光标跳转到匹配符号上停留的时间(*0.1s)
    set matchtime=0
    " 不高亮显示当前行
    set nocursorline
    " 不高亮显示当前列
    set nocursorcolumn
    " 显示高亮
    set hlsearch
    " 即时预览替换命令的效果(nvim only)
    set inccommand=split
    " GVim配色方案
    if GUI()
        colorscheme clearblack
    elseif $TERM == 'xterm' || $TERM == 'xterm-256color' || $TERM == 'tmux-256color'
        set t_Co=256
        colorscheme clearblack
    else
        set t_Co=16
    endif
    " 当运行宏时，不重绘
    set lazyredraw
" }
" { 折叠
    if version >= 702
        " 启用折叠
        set foldenable
        " 设置折叠标识列的宽度
        set foldcolumn=0
        " 设置初始的折叠级别
        set foldlevel=8
        " 设置代码折叠模式
        set foldmethod=marker foldmarker={,} foldlevel=9999
    else
        " Vi不支持以上参数配置
    endif
    " 设置不换行
    set nowrap
    " 自动换行处理, 输入时超出长度自动换到下一行, 0:不启用
    set textwidth=0
    " 整词换行, 需要断行设为ON
    set linebreak
" }
" { 其他
    " 鼠标行为
    if GUI()
        set mouse=a
    else
        set mouse=
    endif
    " 设置光标闪烁行为
    "       a:所有模式
    "       行为参数:block、blinkoff0、blinkwait0
    set guicursor=a:blinkon0
    " 错误时发出警报
    set errorbells
    " 警告响铃
    " autocmd VimEnter * setlocal vb t_vb=
    " 错误时反白闪烁
    set novisualbell
    " 允许不保存文件切换缓冲区
"     set hidden
    " shortens messages to avoid 'press a key' prompt
    set shortmess=atI
    " do not redraw while executing macros (much faster)
    set lazyredraw
    " for easy browse last line with wrap text
    set display+=lastline
    " show tag with function protype.
    set showfulltag
    " In Visual Block Mode, cursor can be positioned where there is no actual character
    set ve=block
    " 命令历史长度
    set history=100
    " 不自动生成备份文件  a.xxx -> a.xxx~
    set nobackup
    set nowritebackup
    " 设置使用交换文件, 用于非正常关闭时恢复
    set swapfile
" }

